#ifndef __FW_FONTMAP_H__
#define __FW_FONTMAP_H__

namespace freewrite
{
	
	struct AllocationToken
	{
		Vector2I16 TexelOffset;
		FontMap* FontMap;
	};

	enum EAllocNodeState
	{
		ANS_UnAllocated = 0,
		ANS_Free,
		ANS_Using,
	};

	struct AllocNode
	{
		int16_t Next;
		EAllocNodeState State;
	};

	class AllocMap2D
	{
		FW_NO_COPYCONSTRUCT(AllocMap2D);

	public:
		std::vector<AllocNode> m_Nodes;
		size_t m_Dim;
		uint32_t m_GridSize;
		int16_t m_UsingHead;
		int16_t m_FreeHead;
		AllocMap2D* m_UpperMip;

		AllocNode* At(int16_t index);

		AllocMap2D(size_t dim, AllocMap2D* upperMip = nullptr)
			: m_Dim(dim)
			, m_GridSize(FW_TEXTURE_DIM / dim)
			, m_Nodes(dim * dim)
			, m_UsingHead(-1)
			, m_FreeHead(-1)
			, m_UpperMip(upperMip)
		{
			Reset();
		}

		void Reset();
		bool Alloc(int16_t& outIndex);
		void Free(int16_t index);
		
		Vector2I16 IndexToXY(int16_t index) const;
		int16_t XYToIndex(int16_t x, int16_t y) const;

		Vector2I16 XYToTexelOffset(int16_t x, int16_t y) const;

	private:
		void NodeUnAlloc(int16_t index);
		void NodeAlloc(int16_t index);
		void NodeFree(int16_t index);
		int16_t NodeUsing();
	};

	class FontMap
	{
		FW_NO_COPYCONSTRUCT(FontMap);

		IFWTexture2D* m_Texture;
		std::vector<AllocMap2D*> m_MipChain;
		friend class FontCache;
	public:
		FontMap(IFWTexture2D* pTexture);
		~FontMap();
		virtual IFWTexture2D* GetTexture() const { return m_Texture; }
		virtual Vector4U16 CalculateSubUV(const Character* pChr) const;
		bool Alloc(Character* chr, AllocationToken* token);
		bool WriteBitmap(uint8_t* pSrc, uint32_t srcPitch, uint32_t width, uint32_t height, AllocationToken* token, bool bDoNotWait);
	};
}

#endif//__FW_FONTMAP_H__